package com.zzhou.common.library.util;



import com.zzhou.common.library.annotation.NotProguard;

import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

/**
 * Created by zhouzhen on 6/29/16.
 */
@NotProguard
public class CipherUtils {

    // 向量
    private final static String iv = "01234567";
    // 加解密统一使用的编码方式
    private final static String encoding = "utf-8";
    /**
     * MD5加密
     * <br>http://stackoverflow.com/questions/1057041/difference-between-java-and-php5-md5-hash
     * <br>http://code.google.com/p/roboguice/issues/detail?id=89
     *
     * @param
     * @return 加密后的字符串
     */
    @NotProguard
    public static String md5(String string) {
        byte[] hash = null;
        try {
            hash = MessageDigest.getInstance("MD5").digest(
                    string.getBytes(encoding));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10)
                hex.append("0");
            hex.append(Integer.toHexString(b & 0xFF));
        }
        return hex.toString();
    }
 public static String test(String data, String value){
//     Log.e("CipherUtils",data);
     return data +value;
 }
    /**
     * 根据指定的密钥及算法，将字符串进行加密。
     * @param data 要进行加密的字符串。
     * @param crkey 秘钥
     * @return  加密后的结果将由byte[]数组转换为64进制表示的数组。如果加密过程失败，将返回null。
     * @throws Exception
     */
    @NotProguard
    public static String encrypt(String data, String crkey){
        try {
            Key key = getDESKey(crkey.getBytes());
            Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
            IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, key, ips);
            byte[] encryptData = cipher.doFinal(data.getBytes(encoding));
            return Base64.encode(encryptData);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 根据指定的密钥及算法，将字符串进行解密。
     * @param data 要进行解密的数据，它是由原来的byte[]数组转化为字符串的结果。
     * @param crkey 秘钥 可以为空，为空采用默认秘钥
     * @return 解密后的结果。它由解密后的byte[]重新创建为String对象。如果解密失败，将返回null。
     * @throws Exception
     */
    @NotProguard
    public static String decrypt(String data, String crkey){

        try {
            Key key = getDESKey(crkey.getBytes());
            Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
            IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, key, ips);

            byte[] decryptData = cipher.doFinal(Base64.decode(data));
            return new String(decryptData, encoding);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
//    /*本地保存密码解密*/
//    public static String decryptPwd(String data) throws Exception{
//        String deckey = "njxtqgjyptfromlianchuang";
//        return decrypt(data,deckey);
//    }
//    /*本地保存密码加密*/
//    public static String encryptPwd(String data) throws Exception{
//        String deckey = "njxtqgjyptfromlianchuang";
//        return encrypt(data,deckey);
//    }
    /**
     * 返回可逆算法DES的密钥
     *
     * @param key 前8字节将被用来生成密钥。
     * @return 生成的密钥
     * @throws Exception
     */
    @NotProguard
    public static Key getDESKey(byte[] key) throws Exception {
        DESedeKeySpec des = new DESedeKeySpec(key);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("desede");
        return keyFactory.generateSecret(des);
    }

//    /**
//     * 根据指定的密钥及算法，将字符串进行解密。
//     *
//     * @param data      要进行解密的数据，它是由原来的byte[]数组转化为字符串的结果。
//     * @param key       密钥。
//     * @param algorithm 算法。
//     * @return 解密后的结果。它由解密后的byte[]重新创建为String对象。如果解密失败，将返回null。
//     * @throws Exception
//     */
//    public static String decrypt(String data, Key key, String algorithm)
//            throws Exception {
//        Cipher cipher = Cipher.getInstance(algorithm);
//        cipher.init(Cipher.DECRYPT_MODE, key);
//        String result = new String(cipher.doFinal(hexStringToByteArray(data)), encoding);
//        return result;
//    }
//
//    /**
//     * 根据指定的密钥及算法对指定字符串进行可逆加密。
//     *
//     * @param data      要进行加密的字符串。
//     * @param key       密钥。
//     * @param algorithm 算法。
//     * @return 加密后的结果将由byte[]数组转换为16进制表示的数组。如果加密过程失败，将返回null。
//     */
//    public static String encrypt(String data, Key key, String algorithm)
//            throws Exception {
//        Cipher cipher = Cipher.getInstance(algorithm);
//        cipher.init(Cipher.ENCRYPT_MODE, key);
//        return byteArrayToHexString(cipher.doFinal(data.getBytes(encoding)));
//    }
//
//    /**
//     * byte[]数组转换为16进制的字符串
//     *
//     * @param data 要转换的字节数组
//     * @return 转换后的结果
//     */
//    public static final String byteArrayToHexString(byte[] data) {
//        StringBuilder sb = new StringBuilder(data.length * 2);
//        for (byte b : data) {
//            int v = b & 0xff;
//            if (v < 16) {
//                sb.append('0');
//            }
//            sb.append(Integer.toHexString(v));
//        }
//        return sb.toString().toUpperCase(Locale.getDefault());
//    }
//
//    /**
//     * 16进制表示的字符串转换为字节数组
//     *
//     * @param s 16进制表示的字符串
//     * @return byte[] 字节数组
//     */
//    public static byte[] hexStringToByteArray(String s) {
//        int len = s.length();
//        byte[] d = new byte[len / 2];
//        for (int i = 0; i < len; i += 2) {
//            // 两位一组，表示一个字节,把这样表示的16进制字符串，还原成一个进制字节
//            d[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character
//                    .digit(s.charAt(i + 1), 16));
//        }
//        return d;
//    }

    public static String MD5Encrypt(String inStr) {
        MessageDigest md = null;
        String outStr = null;
        try {
            md = MessageDigest.getInstance("MD5"); // 可以选中其他的算法如SHA
            byte[] digest = md.digest(inStr.getBytes()); // 返回的是byet[]，要转化为String存储比较方便
            outStr = bytetoString(digest);
        } catch (NoSuchAlgorithmException nsae) {
            nsae.printStackTrace();
        }
        return outStr;
    }

    public  static String bytetoString(byte[] digest) {
        String str = "";
        String tempStr = "";
        for (int i = 0; i < digest.length; i++) {
            tempStr = (Integer.toHexString(digest[i] & 0xff));
            if (tempStr.length() == 1) {
                str = str + "0" + tempStr;
            } else {
                str = str + tempStr;
            }
        }
        return str.toUpperCase();
    }
}
